﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace DiracTCC.Business
{
    public class RGB
    {
        public int Red { get; set; }
        public int Green { get; set; }
        public int Blue { get; set; }

        public int Value
        {
            get
            {
                return Red + Green + Blue;
            }
        }
    }
    public class BitMap
    {
        public int Size { get; set; }
        public int Width { get; set; }
        public int Height { get; set; }
        public List<RGB> Pixels { get; set; }

        public BitMap()
        {
            Pixels = new List<RGB>();
        }
    }
    public class BmpComparer
    {
        public BitMap Bitmap1 { get; set; }
        public BitMap Bitmap2 { get; set; }
        public double Difference { get; set; }

        public BmpComparer(string bmpPath1, string bmpPath2)
        {
            Bitmap1 = GetBitmap(bmpPath1);
            Bitmap2 = GetBitmap(bmpPath2);
            GetDifference();
        }

        private void GetDifference()
        {
            if (Bitmap1.Pixels.Count != Bitmap2.Pixels.Count)
                throw new Exception("Diferent size bmp's can't be compared! Change implementation!!!");

            Difference = 0;
            for (int i = 0; i < Bitmap1.Pixels.Count; i++)
            {
                Difference += Math.Abs(Bitmap1.Pixels[i].Red - Bitmap2.Pixels[i].Red) +
                    Math.Abs(Bitmap1.Pixels[i].Green - Bitmap2.Pixels[i].Green) +
                    Math.Abs(Bitmap1.Pixels[i].Blue - Bitmap2.Pixels[i].Blue);
            }

            Difference = (double)Difference / (double)(3 * Bitmap1.Width * Bitmap1.Height);
        }

        private BitMap GetBitmap(string path)
        {
            BitMap bmp = new BitMap(); ;

            using (FileStream fs = new FileStream(path, FileMode.Open))
            {
                byte[] data = new byte[fs.Length];
                fs.Read(data, 0, data.Length);

                
                bmp.Size = ExtractByteInt(data, 2, 4);
                bmp.Width = ExtractByteInt(data, 18, 4);
                bmp.Height = ExtractByteInt(data, 22, 4);

                int dataPosition = 54;
                int padding = GetPaddind(bmp);
                for (int i = 0; i < bmp.Height; i++)
                {
                    for (int j = 0; j < bmp.Width; j++)
                    {
                        bmp.Pixels.Add(new RGB
                        {
                            Blue = ExtractByteInt(data, dataPosition++, 1),
                            Green = ExtractByteInt(data, dataPosition++, 1),
                            Red = ExtractByteInt(data, dataPosition++, 1)
                        });
                    }

                    padding += padding;
                }
            }

            return bmp;
        }

        private int GetPaddind(BitMap bmp)
        {
            return (bmp.Width % 4 == 0) ? 0 : 4 - bmp.Width % 4;
        }

        private int ExtractByteInt(byte[] data, int initialPosition, int size)
        {
            int value = 0;

            for (int i = 0; i < size; i++)
            {
                value += (int)data[initialPosition + i] * (int)Math.Pow(256, i);
            }

            return value;
        }
    }
}
